home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / misc / unsqsh.lha / unsqsh.c next >
C/C++ Source or Header  |  1999-05-31  |  11KB  |  604 lines

  1. /*
  2.  
  3.   portable code to decrunch XPK-SQSH files
  4.   written from "xpksqsh.library 1.10 (6.3.94)"
  5.  
  6.   (24.12.97) jah@fh-zwickau.de
  7.   tested with sas6.51(m68k) gcc2.7.2(i386) gcc2.7.2(sparc)
  8.  
  9.   (23.01.99) h430827@stud.u-szeged.hu
  10.   fixed problem with raw chunks, added checksum verification
  11.   tested with egcs-2.91.57(i386)
  12.  
  13.   (31.05.99) wepl@kagi.com
  14.   complete reworked, header chksum check added, optimized
  15.   tested with xlC3.1.3(ppc) gcc2.7.2(i486) gcc2.8.1(sparc)
  16.  
  17. */
  18.  
  19. /*
  20. #define debug
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. #define XPKERR_NOXPK 1
  28. #define XPKERR_UNKNOWNCOMP 2
  29. #define XPKERR_FORMAT 3
  30. #define XPKERR_CHKSUM 4
  31. #define XPKERR_UNKNOWNCHUNK 5
  32.  
  33. typedef unsigned char UBYTE;        /* 8 bit */
  34. typedef unsigned short int UWORD;    /* 16 bit */
  35. typedef unsigned long int ULONG;    /* 32 bit */
  36.  
  37. volatile int xpkerrno;
  38.  
  39. static const char *xpkerrtext[] = {
  40.   NULL,
  41.   "not a XPK file",
  42.   "unknown compressor type",
  43.   "data format error",
  44.   "checksum failed",
  45.   "unknown chunk type"
  46. };
  47.  
  48. /*int xpk_check  (UBYTE[16] src, int* srclen, int* dstlen);*/
  49. int  xpk_check  (UBYTE* src, int* srclen, int* dstlen);
  50. int  xpk_unpack (UBYTE* src, UBYTE* dst);
  51. void sqsh       (UBYTE* src, UBYTE* dst);
  52.  
  53. int main(int ac,char *av[]) {
  54.   UBYTE *src;
  55.   UBYTE *dst;
  56.   int srclen;
  57.   int dstlen;
  58.   int rc=1;
  59.  
  60.   if (! (src = (UBYTE*) malloc(16))) {
  61.     fprintf(stderr,"no memory\n");
  62.   } else {
  63.     if (1 != fread(src,16,1,stdin)) {
  64.       perror("error reading source file-header");
  65.     } else {
  66.       if (! xpk_check(src,&srclen,&dstlen)) {
  67.     fprintf(stderr,"%s\n",xpkerrtext[xpkerrno]);
  68.       } else {
  69.     if (! (src = realloc(src,srclen))) {
  70.       fprintf(stderr,"no memory\n");
  71.     } else {
  72.       if (! (dst = malloc(dstlen))) {
  73.         fprintf(stderr,"no memory\n");
  74.       } else {
  75.         if (1 != fread(src+16,srclen-16,1,stdin)) {
  76.           perror("error reading source file");
  77.         } else {
  78.           if (! xpk_unpack(src,dst)) {
  79.         fprintf(stderr,"%s\n",xpkerrtext[xpkerrno]);
  80.           } else {
  81.         if (1 != fwrite(dst,dstlen,1,stdout)) {
  82.           perror("error writing destination file");
  83.         } else {
  84.           rc = 0;
  85.         }
  86.           }
  87.         }
  88.         free(dst);
  89.       }
  90.     }
  91.       }
  92.     }
  93.     free(src);
  94.   }
  95.   return rc;
  96. }
  97.  
  98. /*
  99.  * check the given 16 byte array if it is a valid XPK-SQSH header
  100.  * and returns source and destination legth
  101.  *
  102.  */
  103. int xpk_check  (UBYTE* src, int* srclen, int* dstlen) {
  104.  
  105.   if ('X' != *src++ ||
  106.       'P' != *src++ ||
  107.       'K' != *src++ ||
  108.       'F' != *src++) {
  109.     xpkerrno = XPKERR_NOXPK;
  110.     return 0;
  111.   }
  112.  
  113.   *srclen  = *src++ << 24;
  114.   *srclen |= *src++ << 16;
  115.   *srclen |= *src++ << 8;
  116.   *srclen |= *src++;
  117.  
  118.   if ('S' != *src++ ||
  119.       'Q' != *src++ ||
  120.       'S' != *src++ ||
  121.       'H' != *src++) {
  122.     xpkerrno = XPKERR_UNKNOWNCOMP;
  123.     return 0;
  124.   }
  125.  
  126.   *dstlen  = *src++ << 24;
  127.   *dstlen |= *src++ << 16;
  128.   *dstlen |= *src++ << 8;
  129.   *dstlen |= *src++;
  130.  
  131.   xpkerrno = 0;
  132.   return 1;
  133. }
  134.  
  135.  
  136. /*
  137. ; file header:
  138. ;    0    LONG    "XPKF"
  139. ;    4    LONG    file size - 8
  140. ;    8    LONG    "SQSH"
  141. ;   12    LONG    unpacked size
  142. ;  $10    QUAD    original file header
  143. ;  $20    WORD
  144. ;  $22    WORD
  145. ;  $24  first chunk
  146. ;
  147. ; chunk header:
  148. ;    0  BYTE    type
  149. ;    1  BYTE    checksum
  150. ;    2    WORD    checksum
  151. ;    4    WORD    packed chunk size starting from offset 8, long aligned
  152. ;    6    WORD    unpacked chunk size
  153. ;    8    LABEL    bitstream...
  154. */
  155.  
  156. int xpk_unpack (UBYTE* src, UBYTE* dst) {
  157.   int len;        /* unpacked size */
  158.   UBYTE type;        /* type of chunk */
  159.   UBYTE hchk;        /* chunk header chksum */
  160.   UWORD chk;        /* chunk data chksum */
  161.   UWORD cp;        /* chunk packed length */
  162.   UWORD cu;        /* chunk unpacked length */
  163.   ULONG l, *lp;
  164.  
  165. #ifdef debug
  166.   UBYTE* t=src;        /* used for offset calculation */
  167. #endif
  168.  
  169.   src += 12;        /* skip id's and file size */
  170.   len  = *src++ << 24;
  171.   len |= *src++ << 16;
  172.   len |= *src++ << 8;
  173.   len |= *src++;
  174.   src += 20;        /* skip original file header and ?? */
  175.  
  176.   /* do for each chunk */
  177.   while (len) {
  178.     type = *src++;        /* type of chunk */
  179.     hchk = *src++;        /* chunk header chksum */
  180.     chk  = *(UWORD*)src;    /* chunk data chksum */
  181.     src += 2;
  182.     cp   = *src++ << 8;
  183.     cp  |= *src++;        /* chunk packed length */
  184.     cu   = *src++ << 8;
  185.     cu  |= *src++;        /* chunk unpacked length */
  186.  
  187. #ifdef debug
  188.     fprintf(stderr,"offset=%6x type=%02x chk=%04x cp=%04x cu=%04x",src-t,type,chk,cp,cu);
  189. #endif
  190.  
  191.     /* check chunk header chksum */
  192.     hchk ^= type;
  193.     hchk ^= chk ^ (chk >> 8);
  194.     hchk ^= cp  ^ (cp >> 8);
  195.     hchk ^= cu  ^ (cu >> 8);
  196.     if (hchk) {
  197.       xpkerrno=XPKERR_CHKSUM;
  198.       return 0;
  199.     }
  200.  
  201.     /* make packed chunk size long aligned */
  202.     cp   = (cp + 3) & 0xfffc;
  203.     
  204.     /* check chunk data chksum */
  205.     for (l=0,lp=(ULONG*)(src+cp); lp!=(ULONG*)src; ) l ^= *--lp;
  206.     chk ^= l & 0xffff;
  207.     chk ^= l >> 16;
  208.     if (chk) {
  209.       xpkerrno=XPKERR_CHKSUM;
  210.       return 0;
  211.     }
  212.     
  213.     /* check chunk type */
  214.     switch (type) {
  215.     case 0:
  216.       /* unpacked */
  217.       memcpy(dst,src,cu);
  218.       dst += cu;
  219.       src += cp;
  220.       len -= cu;
  221.       continue;
  222.     case 1:
  223.       /* SQSH packed */
  224.       sqsh(src,dst);
  225.       dst += cu;
  226.       src += cp;
  227.       len -= cu;
  228.       continue;
  229.     default:
  230.       /* unknown type */
  231.       xpkerrno=XPKERR_UNKNOWNCHUNK;
  232.       return 0;
  233.     }
  234.   }
  235.   xpkerrno = 0;
  236.   return 1;
  237. }
  238.  
  239. int bfextu(UBYTE *p,int bo,int bc) {
  240.   int r;
  241.  
  242.   p += bo / 8;
  243.   r = *(p++);
  244.   r <<= 8;
  245.   r |= *(p++);
  246.   r <<= 8;
  247.   r |= *p;
  248.   r <<= bo % 8;
  249.   r &= 0xffffff;
  250.   r >>= 24 - bc;
  251.  
  252.   return r;
  253. }
  254.  
  255. #define bfextu1 ((*(src + d0 / 8) >> 7 - (d0 % 8)) & 1)
  256.  
  257. int bfextu3(UBYTE *p,int bo) {
  258.   int r;
  259.  
  260.   p += bo / 8;
  261.   r = *(p++);
  262.   r <<= 8;
  263.   r |= *p;
  264.   r >>= 13 - (bo % 8);
  265.   r &= 7;
  266.  
  267.   return r;
  268. }
  269.  
  270. int bfexts(UBYTE *p,int bo,int bc) {
  271.   int r;
  272.  
  273.   p += bo / 8;
  274.   r = *(p++);
  275.   r <<= 8;
  276.   r |= *(p++);
  277.   r <<= 8;
  278.   r |= *p;
  279.   r <<= (bo % 8) + 8;
  280.   r >>= 32 - bc;
  281.  
  282.   return r;
  283. }
  284.  
  285. void sqsh(UBYTE *src, UBYTE *dst) {
  286.   int d0,d1,d2,d3,d4,d5,d6,a2,a5;
  287.   UBYTE *a4,*a6;
  288.   UBYTE a3[] = { 2,3,4,5,6,7,8,0,3,2,4,5,6,7,8,0,4,3,5,2,6,7,8,0,5,4,
  289.     6,2,3,7,8,0,6,5,7,2,3,4,8,0,7,6,8,2,3,4,5,0,8,7,6,2,3,4,5,0 };
  290.  
  291. #ifdef debug
  292.     fprintf(stderr,"=%02x%02x dst=%x",*src,*(src+1),dst);
  293. #endif
  294.  
  295.     a6 = dst;
  296.     a6 += *src++ << 8;
  297.     a6 += *src++;
  298.     d0 = d1 = d2 = d3 = a2 = 0;
  299.  
  300.     d3 = *(src++);
  301.     *(dst++) = d3;
  302.  
  303. l6c6:    if (d1 >= 8) goto l6dc;
  304.     if (bfextu1) goto l75a;
  305.     d0 ++;
  306.     d5 = 0;
  307.     d6 = 8;
  308.     goto l734;
  309.  
  310. l6dc:    if (bfextu1) goto l726;
  311.     d0 ++;
  312.     if (! bfextu1) goto l75a;
  313.     d0 ++;
  314.     if (bfextu1) goto l6f6;
  315.     d6 = 2;
  316.     goto l708;
  317.  
  318. l6f6:    d0 ++;
  319.     if (! bfextu1) goto l706;
  320.     d6 = bfextu3(src,d0);
  321.     d0 += 3;
  322.     goto l70a;
  323.  
  324. l706:    d6 = 3;
  325. l708:    d0 ++;
  326. l70a:    d6 = *(a3 + (8*a2) + d6 - 17);
  327.     if (d6 != 8) goto l730;
  328. l718:    if (d2 < 20) goto l722;
  329.     d5 = 1;
  330.     goto l732;
  331.  
  332. l722:    d5 = 0;
  333.     goto l734;
  334.  
  335. l726:    d0 += 1;
  336.     d6 = 8;
  337.     if (d6 == a2) goto l718;
  338.     d6 = a2;
  339. l730:    d5 = 4;
  340. l732:    d2 += 8;
  341. l734:    d4 = bfexts(src,d0,d6);
  342.     d0 += d6;
  343.     d3 -= d4;
  344.     *dst++ = d3;
  345.     d5--;
  346.     if (d5 != -1) goto l734;
  347.     if (d1 == 31) goto l74a;
  348.     d1 += 1;
  349. l74a:    a2 = d6;
  350. l74c:    d6 = d2;
  351.     d6 >>= 3;
  352.     d2 -= d6;
  353.     if (dst < a6) goto l6c6;
  354.  
  355. #ifdef debug
  356.     fprintf(stderr," dst=%p a6=%p d0=8*%x+%d->%x\n",dst,a6,d0/8,d0%8,(d0+7)/8+3);
  357. /*    fprintf(stderr,"d1=%x d2=%x d3=%x d4=%x d5=%x d6=%x a2=%x a4=%x a5=%x\n",d1,d2,d3,d4,d5,d6,a2,a4,a5); */
  358. #endif
  359.  
  360.     return;
  361.  
  362. l75a:    d0++;
  363.     if (bfextu1) goto l766;
  364.     d4 = 2;
  365.     goto l79e;
  366.  
  367. l766:    d0++;
  368.     if (bfextu1) goto l772;
  369.     d4 = 4;
  370.     goto l79e;
  371.  
  372. l772:    d0++;
  373.     if (bfextu1) goto l77e;
  374.     d4 = 6;
  375.     goto l79e;
  376.  
  377. l77e:    d0++;
  378.     if (bfextu1) goto l792;
  379.     d0++;
  380.     d6 = bfextu3(src,d0);
  381.     d0 += 3;
  382.     d6 += 8;
  383.     goto l7a8;
  384.  
  385. l792:    d0++;
  386.     d6 = bfextu(src,d0,5);
  387.     d0 += 5;
  388.     d4 = 16;
  389.     goto l7a6;
  390.  
  391. l79e:    d0++;
  392.     d6 = bfextu1;
  393.     d0 ++;
  394. l7a6:    d6 += d4;
  395. l7a8:    if (bfextu1) goto l7c4;
  396.     d0 ++;
  397.     if (bfextu1) goto l7bc;
  398.     d5 = 8;
  399.     a5 = 0;
  400.     goto l7ca;
  401.  
  402. l7bc:    d5 = 14;
  403.     a5 = -0x1100;
  404.     goto l7ca;
  405.  
  406. l7c4:    d5 = 12;
  407.     a5 = -0x100;
  408. l7ca:    d0++;
  409.     d4 = bfextu(src,d0,d5);
  410.     d0 += d5;
  411.     d6 -= 3;
  412.     if (d6 < 0) goto l7e0;
  413.     if (d6 == 0) goto l7da;
  414.     d1 -= 1;
  415. l7da:    d1 -= 1;
  416.     if (d1 >= 0) goto l7e0;
  417.     d1 = 0;
  418. l7e0:    d6 += 2;
  419.     a4 = -1 + dst + a5 - d4;
  420. l7ex:    *dst++ = *a4++;
  421.     d6--;
  422.     if (d6 != -1) goto l7ex;
  423.     d3 = *(--a4);
  424.     goto l74c;
  425. }
  426.  
  427. /*
  428. Unpack    move.l    a6,-(sp)
  429.     movea.l    a0,a6
  430.     movea.l    (a6),a0        xsp_InBuf
  431.     movea.l    (8,a6),a1    xsp_OutBuf
  432.     moveq    #0,d7
  433.     move.w    (a0)+,d7
  434.     move.l    d7,($10,a6)
  435.     bsr.b    lbc0006b0
  436.     moveq    #0,d0
  437.     movea.l    (sp)+,a6
  438.     rts
  439.  
  440. lbc0006b0    movea.l    a1,a6
  441.     adda.l    d7,a6
  442.     moveq    #0,d0
  443.     moveq    #0,d1
  444.     moveq    #0,d2
  445.     moveq    #0,d3
  446.     suba.w    a2,a2
  447.     lea    (data_a3,pc),a3
  448.     move.b    (a0)+,d3
  449.     move.b    d3,(a1)+
  450. lbc0006c6    cmp.w    #8,d1
  451.     bcc.b    lbc0006dc
  452.     bftst    (a0){d0:1}
  453.     bne.w    lbc00075a
  454.     addq.l    #1,d0
  455.     moveq    #0,d5
  456.     moveq    #8,d6
  457.     bra.b    lbc000734
  458.  
  459. lbc0006dc    bftst    (a0){d0:1}
  460.     bne.b    lbc000726
  461.     addq.l    #1,d0
  462.     bftst    (a0){d0:1}
  463.     beq.b    lbc00075a
  464.     addq.l    #1,d0
  465.     bftst    (a0){d0:1}
  466.     bne.b    lbc0006f6
  467.     moveq    #2,d6
  468.     bra.b    lbc000708
  469.  
  470. lbc0006f6    addq.l    #1,d0
  471.     bftst    (a0){d0:1}
  472.     beq.b    lbc000706
  473.     bfextu    (a0){d0:3},d6
  474.     addq.l    #3,d0
  475.     bra.b    lbc00070a
  476.  
  477. lbc000706    moveq    #3,d6
  478. lbc000708    addq.l    #1,d0
  479. lbc00070a    lea    (-$10,a3,a2.w*8),a4
  480.     move.b    (-1,a4,d6.w),d6
  481.     cmp.w    #8,d6
  482.     bne.b    lbc000730
  483. lbc000718    cmp.w    #$14,d2
  484.     bcs.b    lbc000722
  485.     moveq    #1,d5
  486.     bra.b    lbc000732
  487.  
  488. lbc000722    moveq    #0,d5
  489.     bra.b    lbc000734
  490.  
  491. lbc000726    addq.l    #1,d0
  492.     moveq    #8,d6
  493.     cmpa.w    d6,a2
  494.     beq.b    lbc000718
  495.     move.l    a2,d6
  496. lbc000730    moveq    #4,d5
  497. lbc000732    addq.w    #8,d2
  498. lbc000734    bfexts    (a0){d0:d6},d4
  499.     add.l    d6,d0
  500.     sub.b    d4,d3
  501.     move.b    d3,(a1)+
  502.     dbra    d5,lbc000734
  503.     cmp.w    #$1f,d1
  504.     beq.b    lbc00074a
  505.     addq.w    #1,d1
  506. lbc00074a    movea.w    d6,a2
  507. lbc00074c    move.w    d2,d6
  508.     lsr.w    #3,d6
  509.     sub.w    d6,d2
  510.     cmpa.l    a6,a1
  511.     blt.w    lbc0006c6
  512.     rts
  513.  
  514. lbc00075a    addq.l    #1,d0
  515.     bftst    (a0){d0:1}
  516.     bne.b    lbc000766
  517.     moveq    #2,d4
  518.     bra.b    lbc00079e
  519.  
  520. lbc000766    addq.l    #1,d0
  521.     bftst    (a0){d0:1}
  522.     bne.b    lbc000772
  523.     moveq    #4,d4
  524.     bra.b    lbc00079e
  525.  
  526. lbc000772    addq.l    #1,d0
  527.     bftst    (a0){d0:1}
  528.     bne.b    lbc00077e
  529.     moveq    #6,d4
  530.     bra.b    lbc00079e
  531.  
  532. lbc00077e    addq.l    #1,d0
  533.     bftst    (a0){d0:1}
  534.     bne.b    lbc000792
  535.     addq.l    #1,d0
  536.     bfextu    (a0){d0:3},d6
  537.     addq.l    #3,d0
  538.     addq.l    #8,d6
  539.     bra.b    lbc0007a8
  540.  
  541. lbc000792    addq.l    #1,d0
  542.     bfextu    (a0){d0:5},d6
  543.     addq.l    #5,d0
  544.     moveq    #$10,d4
  545.     bra.b    lbc0007a6
  546.  
  547. lbc00079e    addq.l    #1,d0
  548.     bfextu    (a0){d0:1},d6
  549.     addq.l    #1,d0
  550. lbc0007a6    add.w    d4,d6
  551. lbc0007a8    bftst    (a0){d0:1}
  552.     bne.b    lbc0007c4
  553.     addq.l    #1,d0
  554.     bftst    (a0){d0:1}
  555.     bne.b    lbc0007bc
  556.     moveq    #8,d5
  557.     suba.w    a5,a5
  558.     bra.b    lbc0007ca
  559.  
  560. lbc0007bc    moveq    #14,d5
  561.     movea.w    #$ef00,a5
  562.     bra.b    lbc0007ca
  563.  
  564. lbc0007c4    moveq    #12,d5
  565.     movea.w    #$ff00,a5
  566. lbc0007ca    addq.l    #1,d0
  567.     bfextu    (a0){d0:d5},d4
  568.     add.l    d5,d0
  569.     subq.w    #3,d6
  570.     bcs.b    lbc0007e0
  571.     beq.b    lbc0007da
  572.     subq.w    #1,d1
  573. lbc0007da    subq.w    #1,d1
  574.     bge.b    lbc0007e0
  575.     moveq    #0,d1
  576. lbc0007e0    addq.w    #2,d6
  577.     lea    (-1,a1,a5.w),a4
  578.     suba.w    d4,a4
  579.     lsr.w    #1,d6
  580.     bcc.b    lbc0007ee
  581. lbc0007ec    move.b    (a4)+,(a1)+
  582. lbc0007ee    move.b    (a4)+,(a1)+
  583.     dbra    d6,lbc0007ec
  584.     move.b    -(a4),d3
  585.     bra.w    lbc00074c
  586.  
  587. data_a3    dc.l    $2030405
  588.     dc.l    $6070800
  589.     dc.l    $3020405
  590.     dc.l    $6070800
  591.     dc.l    $4030502
  592.     dc.l    $6070800
  593.     dc.l    $5040602
  594.     dc.l    $3070800
  595.     dc.l    $6050702
  596.     dc.l    $3040800
  597.     dc.l    $7060802
  598.     dc.l    $3040500
  599.     dc.l    $8070602
  600.     dc.l    $3040500
  601.     dc.b    0
  602.     dc.b    0
  603. */
  604.